// 封装 axios
import axios from 'axios'
import { store } from '@/store/store'
import { Toast } from 'antd-mobile'
import { customHistory } from './history'
import { clearToken, setToken } from './token'
// import { logout } from '@/store/actions'

const http = axios.create({
  // baseURL: 'http://geek.itheima.net/v1_0',
  baseURL: 'http://toutiao.itheima.net/v1_0',
  timeout: 5000,
})

// 将来可以继续进行 拦截器 的处理

// 请求拦截器
http.interceptors.request.use((config) => {
  // console.log('config', config)
  // config 处理流程中配置对象
  // 根据url 添加token
  const token = store.getState().login.token

  // 除了登录外的接口，都传token
  if (!config.url?.startsWith('/authorizations')) {
    // 添加token
    // 此处，需要使用 非空断言 ！ 来去掉 headers 类型中的 undefined 类型
    config.headers!.Authorization = `Bearer ${token}`
  }

  // 别忘了把 config交给后面的函数处理
  return config
})

// 响应拦截器
http.interceptors.response.use(undefined, async (error) => {
  // console.log('error', error)
  // 响应失败时，会执行此处的回调函数
  // 网路超时 处理超时
  if (!error.response) {
    Toast.show({
      // 这是开发者对异常的统一处理
      content: '网络繁忙，请稍后再试',
      duration: 2000,
    })
    // 把错误处理权交换给axios
    return Promise.reject(error)
  }

  // token 过期，登录超时
  if (error.response.status === 401) {
    try {
      // 1.换取token
      // 1.1拿到 refresh_token
      const refresh_token = store.getState().login.refresh_token
      if (!refresh_token) {
        throw Error('refresh_token不存在')
      }
      // 1.2 发起新的请求
      const res = await axios.put(
        // 'http://geek.itheima.net/v1_0/authorizations',
        'http://toutiao.itheima.net/v1_0/authorizations',
        null,
        {
          headers: { Authorization: `Bearer ${refresh_token}` },
        }
      )
      console.log('获取到的新token', res)
      const newToken = {
        token: res.data.data.token,
        refresh_token: refresh_token,
      }
      console.log('newToken==>', newToken)
      // 保存到本地
      setToken(newToken)
      // 保存到redux
      store.dispatch({
        type: 'login/token',
        payload: newToken,
      })
      // 4 继续发送原来请求, 并将处理权交给axios
      // 可以直接使用 axios 实例的 http(配置对象)，它的返回值还是一个 Promise，所以这里要return。
      return http(error.config)
    } catch (error) {
      // 2.重新获取token失败
      clearToken()
      // 清空redux中的token,只能dispatch 对象形式的action
      store.dispatch({
        type: 'login/token',
        payload: { token: '', refresh_token: '' },
      })
      // 提示用户
      Toast.show({
        content: 'Token认证失败,请重新登录',
        duration: 1000,
        afterClose: () => {
          customHistory.push('/login', {
            from: customHistory.location.pathname,
          })
          // 触发退出 action，将 token 等清除
          // store.dispatch(logout())
        },
      })
    }

    return Promise.reject(error)
  }

  // 把错误处理权交还给axios
  return Promise.reject(error)
})

export { http }
